package com.hjj.homieMatching.manager;

import com.hjj.homieMatching.common.ErrorCode;
import com.hjj.homieMatching.constant.RedisConstant;
import com.hjj.homieMatching.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;
    
    // 特定路径的限流配置可以在这里调整
    private static final Map<String, Integer> SPECIAL_LIMITS = new HashMap<>();
    
    static {
        // 为特定路径设置更宽松的限制 - 特别是为了测试和开发环境
        SPECIAL_LIMITS.put(RedisConstant.AVATAR_UPLOAD_KEY, 200); // 设置头像上传更宽松的限制
    }

    /**
     * 执行限流
     * @param key 限流键
     * @param time 允许的请求次数
     * @param frequency 时间窗口（分钟）
     */
    public void doRateLimiter(String key, long time, long frequency) {
        try {
            // 检查是否有特殊路径需要不同的限制
            if (key.startsWith(RedisConstant.AVATAR_UPLOAD_KEY)) {
                // 对头像上传应用宽松的限制
                log.info("应用头像上传特殊限制，键: {}", key);
                time = SPECIAL_LIMITS.getOrDefault(RedisConstant.AVATAR_UPLOAD_KEY, (int)time);
            }
            
            RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
            rateLimiter.trySetRate(RateType.OVERALL, time, frequency, RateIntervalUnit.MINUTES);
            boolean acquired = rateLimiter.tryAcquire();
            if (!acquired) {
                // Redisson 4.x 没有 remainTimeToRefill 方法，改为固定提示
                log.warn("{}请求次数过多，请稍后重试", key);
                throw new BusinessException(ErrorCode.TOO_MANY_REQUEST, "请稍后再试，每分钟最多" + time + "次请求");
            }
        } catch (BusinessException e) {
            // 传递业务异常
            throw e;
        } catch (Exception e) {
            // 处理 Redisson 可能的异常
            log.error("限流器异常: {}", e.getMessage(), e);
            // 在出现 Redis 连接问题时避免阻塞服务 - 让请求通过但记录日志
            log.warn("限流器异常，允许请求继续: {}", key);
        }
    }
}
